{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "############## PLEASE RUN THIS CELL FIRST! ###################\n",
    "\n",
    "# import everything and define a test runner function\n",
    "from importlib import reload\n",
    "from helper import run\n",
    "import ecc\n",
    "import helper\n",
    "import op\n",
    "import script\n",
    "import tx"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 1\n",
    "\n",
    "Write the `op_checkmultisig` function of `op.py`.\n",
    "\n",
    "#### Make [this test](/edit/code-ch08/op.py) pass: `op.py:OpTest:test_op_checkmultisig`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercise 1\n",
    "\n",
    "reload(op)\n",
    "run(op.OpTest(\"test_op_checkmultisig\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from helper import encode_base58_checksum\n",
    "h160 = bytes.fromhex('74d691da1574e6b3c192ecfb52cc8984ee7b6c56')\n",
    "print(encode_base58_checksum(b'\\x05' + h160))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 2\n",
    "\n",
    "Write `h160_to_p2pkh_address` that converts a 20-byte hash160 into a p2pkh address.\n",
    "\n",
    "#### Make [this test](/edit/code-ch08/helper.HelperTest.py) pass: `helper.HelperTest.py::test_p2pkh_address`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercise 2\n",
    "\n",
    "reload(helper.HelperTest)\n",
    "run(helper.HelperTest.(\"test_p2pkh_address\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 3\n",
    "\n",
    "Write `h160_to_p2sh_address` that converts a 20-byte hash160 into a p2sh address.\n",
    "\n",
    "#### Make [this test](/edit/code-ch08/helper.HelperTest.py) pass: `helper.HelperTest.py::test_p2sh_address`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercise 3\n",
    "\n",
    "reload(helper.HelperTest)\n",
    "run(helper.HelperTest.(\"test_p2sh_address\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from helper import hash256\n",
    "modified_tx = bytes.fromhex('0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a000000475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b9089325a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028ad2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c56870000000001000000')\n",
    "s256 = hash256(modified_tx)\n",
    "z = int.from_bytes(s256, 'big')\n",
    "print(hex(z))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from ecc import S256Point, Signature\n",
    "from helper import hash256\n",
    "modified_tx = bytes.fromhex('0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a000000475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b9089325a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028ad2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c56870000000001000000')\n",
    "h256 = hash256(modified_tx)\n",
    "z = int.from_bytes(h256, 'big')\n",
    "sec = bytes.fromhex('022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb70')\n",
    "der = bytes.fromhex('3045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a89937')\n",
    "point = S256Point.parse(sec)\n",
    "sig = Signature.parse(der)\n",
    "print(point.verify(z, sig))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 4\n",
    "\n",
    "Validate the second signature from the transaction above."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercise 4\n",
    "\n",
    "from io import BytesIO\n",
    "from ecc import S256Point, Signature\n",
    "from helper import encode_varint, hash256, int_to_little_endian\n",
    "from script import Script\n",
    "from tx import Tx, SIGHASH_ALL\n",
    "\n",
    "hex_tx = '0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a000000db00483045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a8993701483045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402201475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b9089325a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028ad2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c568700000000'\n",
    "hex_sec = '03b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb71'\n",
    "hex_der = '3045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e754022'\n",
    "hex_redeem_script = '475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152ae'\n",
    "sec = bytes.fromhex(hex_sec)\n",
    "der = bytes.fromhex(hex_der)\n",
    "redeem_script = Script.parse(BytesIO(bytes.fromhex(hex_redeem_script)))\n",
    "stream = BytesIO(bytes.fromhex(hex_tx))\n",
    "\n",
    "# modify the transaction\n",
    "# start with version\n",
    "# add number of inputs\n",
    "# modify the single TxIn to have the ScriptSig to be the RedeemScript\n",
    "# add the number of outputs\n",
    "# add each output serialization\n",
    "# add the locktime\n",
    "# add the SIGHASH_ALL\n",
    "# hash256 the result\n",
    "# interpret as a Big-Endian number\n",
    "# parse the S256Point\n",
    "# parse the Signature\n",
    "# verify that the point, z and signature work"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 5\n",
    "\n",
    "Modify the `sig_hash` and `verify_input` methods to be able to verify p2sh transactions.\n",
    "\n",
    "#### Make [this test](/edit/code-ch08/tx.py) pass: `tx.py:TxTest:test_verify_p2sh`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercise 5\n",
    "\n",
    "reload(tx)\n",
    "run(tx.TxTest(\"test_verify_p2sh\"))"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 2
}
